package gossip.v2.util;

import com.baidu.bjf.remoting.protobuf.Codec;
import com.baidu.bjf.remoting.protobuf.ProtobufProxy;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class SerializationUtils {

    private static final ConcurrentMap<Class<?>, Codec<?>> CODEC_CACHE = new ConcurrentHashMap<>();

    @SuppressWarnings("unchecked")
    public static <T> Codec<T> getCodec(Class<T> clazz) {
        return (Codec<T>) CODEC_CACHE.computeIfAbsent(clazz, k -> {
            try {
                return ProtobufProxy.create(clazz);
            } catch (Exception e) {
                throw new SerializationException("Codec creation failed", e);
            }
        });
    }

    public static byte[] serialize(Object obj) {
        if (obj == null) return new byte[0];
        if (obj instanceof byte[]) return (byte[]) obj;

        try {
            Codec<Object> codec = (Codec<Object>) getCodec(obj.getClass());
            return codec.encode(obj);
        } catch (IOException e) {
            throw new SerializationException("Serialization failed", e);
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T deserialize(byte[] bytes, Class<T> clazz) {
        if (bytes == null || bytes.length == 0) return null;

        try {
            Codec<T> codec = getCodec(clazz);
            return codec.decode(bytes);
        } catch (IOException e) {
            throw new SerializationException("Deserialization failed", e);
        }
    }

    public static class SerializationException extends RuntimeException {
        public SerializationException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}
